import json
import re
import os
import sys

try:
    import requests
except ImportError:
    print("未检测到requests库，正在使用清华镜像自动安装...")
    import subprocess
    subprocess.check_call([sys.executable, "-m", "pip", "install", "requests", "-i", "https://pypi.tuna.tsinghua.edu.cn/simple"])
    import requests

# ==============================================================================
# ---                           配置区域                         ---
# ==============================================================================
MAPPING_FILE_PATH = "miao-plugin/resources/meta-sr/material/data.json" # 喵喵星铁材料文件路径（绝对路径！)
USE_NEW_API = True # 是否使用API获取角色列表
CUSTOM_IDS = [] # 自定义角色ID列表，多个用,隔开
OUTPUT_BASE_DIR = "miao-plugin/resources/meta-sr/weapon"  # 绝对路径
GENERATE_SUMMARY_FILES = True # 是否生成汇总文件

# ==============================================================================
# ---                          脚本核心代码                      ---
# ==============================================================================

API_NAME_CACHE = {}
NAME_TO_ID_CACHE = {}
TYPE_MAPPING = {
    "Warrior": "毁灭", "Rogue": "巡猎", "Mage": "智识", "Shaman": "同谐",
    "Warlock": "虚无", "Knight": "存护", "Priest": "丰饶", "Memory": "记忆"
}

def load_id_mapping(mapping_path):
    if NAME_TO_ID_CACHE: return True
    if not os.path.isabs(mapping_path):
        print(f"错误：映射文件路径 '{mapping_path}' 不是绝对路径。", file=sys.stderr)
        return False
    if not os.path.exists(mapping_path):
        print(f"错误：映射文件 '{mapping_path}' 未找到。", file=sys.stderr)
        return False
    try:
        with open(mapping_path, 'r', encoding='utf-8') as f:
            mapping_data = json.load(f)
        for category in mapping_data.values():
            for item_id, details in category.items():
                if name := details.get("name"): NAME_TO_ID_CACHE[name] = item_id
        print(f"成功加载并缓存 '{os.path.basename(mapping_path)}'。")
        return True
    except Exception as e:
        print(f"错误：加载映射文件 '{mapping_path}' 出错: {e}", file=sys.stderr)
        return False

def get_final_material_id(original_id, mapping_available):
    original_id_str = str(original_id)
    if not mapping_available: return original_id_str
    if item_name := API_NAME_CACHE.get(original_id_str):
        return str(NAME_TO_ID_CACHE.get(item_name, original_id_str))
    
    api_url = f"https://api.hakush.in/hsr/data/cn/item/{original_id_str}.json"
    try:
        print(f"  > 正在请求材料ID {original_id_str} 的名称...")
        response = requests.get(api_url, timeout=10)
        response.raise_for_status()
        item_name = response.json().get("ItemName")
        if item_name: API_NAME_CACHE[original_id_str] = item_name
        return str(NAME_TO_ID_CACHE.get(item_name, original_id_str))
    except requests.exceptions.RequestException:
        return original_id_str

def format_skill_value(value, suffix):
    val = value * 100 if '%' in suffix else value
    return str(int(val)) if val == int(val) else f"{val:.1f}"

def transform_lightcone_data(source_data, lightcone_id, mapping_available):
    lc_id_str = str(lightcone_id)
    type_en = source_data.get("BaseType", "Unknown")
    type_cn = TYPE_MAPPING.get(type_en, "未知")
    
    sanitized_desc = re.sub(r'</?[^>]+>', '', source_data.get("Desc", ""))
    final_desc = sanitized_desc.replace('\\n', '<br />')

    target = {
        "id": lc_id_str, "name": source_data.get("Name", ""),
        "star": int(re.search(r'\d+$', source_data.get("Rarity", "0")).group() or 0),
        "desc": final_desc, "type": type_cn, "typeId": 0
    }

    if stats := source_data.get("Stats"):
        grow = {"atk": stats[0].get("BaseAttackAdd", 0), "hp": stats[0].get("BaseHPAdd", 0), "def": stats[0].get("BaseDefenceAdd", 0)}
        last = stats[-1]; max_lvl = last.get("MaxLevel", 80)
        target["baseAttr"] = {"atk": round(last.get("BaseAttack", 0) + (max_lvl - 1) * grow["atk"], 2), "hp": round(last.get("BaseHP", 0) + (max_lvl - 1) * grow["hp"], 2), "def": round(last.get("BaseDefence", 0) + (max_lvl - 1) * grow["def"], 2)}
        target["growAttr"] = grow
        target["attr"] = {}
        for i, p in enumerate(stats):
            costs = {get_final_material_id(item["ItemID"], mapping_available): item["ItemNum"] for item in p.get("PromotionCostList", [])}
            target["attr"][str(i)] = {"promote": p.get("Promotion", i), "maxLevel": p.get("MaxLevel", 0), "cost": costs, "attrs": {"atk": p.get("BaseAttack", 0), "hp": p.get("BaseHP", 0), "def": p.get("BaseDefence", 0)}}

    if ref := source_data.get("Refinements"):
        original_desc = ref.get("Desc", "")
        tables = {}
        processed_desc_parts = []
        last_end = 0
        dynamic_param_counter = 0

        if (lvls := ref.get("Level")) and "1" in lvls:
            num_params = len(lvls["1"].get("ParamList", []))
            param_values_by_level = {i: [lvls[str(lvl)]["ParamList"][i] for lvl in range(1, 6)] for i in range(num_params)}
            
            placeholder_pattern = r'(<color=.*?>)?<unbreak>(.*?)<\/unbreak>(<\/color>)?'

            for match in re.finditer(placeholder_pattern, original_desc):
                processed_desc_parts.append(original_desc[last_end:match.start()])
                content = match.group(2)
                param_match = re.match(r'#(\d+)\[.*?\](.*)', content)

                if param_match:
                    param_index, suffix = int(param_match.group(1)) - 1, param_match.group(2)
                    if param_index in param_values_by_level:
                        values = param_values_by_level[param_index]
                        if len(set(values)) == 1:
                            processed_desc_parts.append(format_skill_value(values[0], suffix) + suffix)
                        else:
                            dynamic_param_counter += 1
                            table_key = str(dynamic_param_counter)
                            table_values = []
                            for v in values:
                                val = v * 100 if '%' in suffix else v
                                val = round(val, 5)
                                table_values.append(int(val) if val == int(val) else round(val, 1))
                            tables[table_key] = table_values
                            processed_desc_parts.append(f"<nobr>${table_key}[i]{suffix}</nobr>")
                else:
                    processed_desc_parts.append(content)
                last_end = match.end()

            processed_desc_parts.append(original_desc[last_end:])
            interim_desc = "".join(processed_desc_parts)

            def nobr_num_repl(m):
                return f"<nobr>{m.group(0)}</nobr>"

            def nobr_replacer(m):
                if m.group(1):
                    return m.group(1)
                elif m.group(2):
                    return f"<nobr>{m.group(2)}</nobr>"
                return m.group(0)

            combined_pattern = r'(<nobr>.*?</nobr>)|(?<![$])(\d+(?:\.\d+)?%?)(?![\[]|</nobr>)'

            interim_desc = re.sub(combined_pattern, nobr_replacer, interim_desc)

            def span_elem_repl(m):
                return f"<span>{m.group(0)}</span>"

            elem_keywords = ['火', '冰', '风', '雷', '物理', '量子', '虚数']
            elem_pattern = '|'.join(elem_keywords)
            interim_desc = re.sub(f'({elem_pattern})', span_elem_repl, interim_desc)

            final_processed_desc = interim_desc.replace('\\n', '<br />')

        target["skill"] = {"id": int(lc_id_str), "name": ref.get("Name", ""), "desc": final_processed_desc, "tables": tables}
    
    return target

def download_and_save_image(url, save_path):
    try:
        response = requests.get(url, timeout=15)
        response.raise_for_status()
        with open(save_path, 'wb') as f:
            f.write(response.content)
        print(f"  > 成功保存图片: {save_path}")
    except requests.exceptions.RequestException as e:
        print(f"  > 警告：下载图片失败 {url}: {e}", file=sys.stderr)

def process_lightcone(lc_id, mapping_available):
    print(f"\n--- 开始处理光锥 ID: {lc_id} ---")
    api_url = f"https://api.hakush.in/hsr/data/cn/lightcone/{lc_id}.json"
    try:
        response = requests.get(api_url, timeout=15)
        response.raise_for_status()
        source_data = response.json()
    except requests.exceptions.RequestException as e:
        print(f"错误：获取光锥 {lc_id} 数据失败: {e}", file=sys.stderr)
        return
    transformed_data = transform_lightcone_data(source_data, lc_id, mapping_available)
    name = re.sub(r'[\\/*?:"<>|]', "_", transformed_data.get("name", f"未知_{lc_id}"))
    output_dir = os.path.join(OUTPUT_BASE_DIR, transformed_data.get("type", "未知"), name)
    os.makedirs(output_dir, exist_ok=True)
    output_path = os.path.join(output_dir, "data.json")
    with open(output_path, 'w', encoding='utf-8') as f:
        json.dump(transformed_data, f, ensure_ascii=False, indent=2)
    print(f"成功：已将 '{name}' 的数据保存至 '{output_path}'")

    splash_url = f"https://api.hakush.in/hsr/UI/lightconemaxfigures/{lc_id}.webp"
    splash_path = os.path.join(output_dir, "splash.webp")
    download_and_save_image(splash_url, splash_path)

    icon_url = f"https://api.hakush.in/hsr/UI/lightconemediumicon/{lc_id}.webp"
    icon_path = os.path.join(output_dir, "icon.webp")
    download_and_save_image(icon_url, icon_path)
   # 还有个图像不知道哪里搞，就介样吧，又不是不能用
def main():
    if not MAPPING_FILE_PATH or MAPPING_FILE_PATH.strip() == "":
        print("!!! 错误：请先填写脚本中的 MAPPING_FILE_PATH 路径。", file=sys.stderr)
        sys.exit(1)
    if not os.path.isabs(OUTPUT_BASE_DIR):
        print(f"!!! 错误：请将 OUTPUT_BASE_DIR 配置为绝对路径，当前为: {OUTPUT_BASE_DIR}", file=sys.stderr)
        sys.exit(1)
    mapping_available = load_id_mapping(MAPPING_FILE_PATH)
    ids_to_process = set()
    if USE_NEW_API:
        api_url = "https://api.hakush.in/hsr/new.json"
        print(f"\n正在从 {api_url} 获取最新光锥列表...")
        try:
            response = requests.get(api_url, timeout=15)
            response.raise_for_status()
            api_ids = response.json().get("lightcone", [])
            print(f"  > API返回 {len(api_ids)} 个光锥ID。")
            ids_to_process.update(api_ids)
        except requests.exceptions.RequestException as e:
            print(f"警告：无法从API获取ID列表: {e}", file=sys.stderr)
    if CUSTOM_IDS:
        print(f"从配置中添加 {len(CUSTOM_IDS)} 个自定义ID。")
        ids_to_process.update(CUSTOM_IDS)
    if not ids_to_process:
        print("\n没有找到任何需要处理的光锥ID，程序退出。")
        return
    print(f"\n总计将要处理 {len(ids_to_process)} 个唯一的光锥ID。")
    summary = {}
    for lc_id in sorted(ids_to_process, key=lambda x: int(str(x))):
        process_lightcone(lc_id, mapping_available)
        for t in TYPE_MAPPING.values():
            possible_dir = os.path.join(OUTPUT_BASE_DIR, t)
            if os.path.exists(possible_dir):
                for name in os.listdir(possible_dir):
                    lc_dir = os.path.join(possible_dir, name)
                    data_path = os.path.join(lc_dir, "data.json")
                    if os.path.exists(data_path):
                        try:
                            with open(data_path, "r", encoding="utf-8") as f:
                                data = json.load(f)
                            summary[data["id"]] = {
                                "id": data["id"],
                                "name": data["name"],
                                "type": data["type"],
                                "star": data["star"]
                            }
                        except Exception:
                            continue

    if GENERATE_SUMMARY_FILES:
        summary_path = os.path.join(OUTPUT_BASE_DIR, "data.json")
        with open(summary_path, "w", encoding="utf-8") as f:
            json.dump(summary, f, ensure_ascii=False, indent=2)
        print(f"已生成汇总文件: {summary_path}")
    print(f"\n--- 所有任务处理完毕 ---")

if __name__ == "__main__":
    main()